import os
import logging
import datetime
import traceback
from mongolog.models import UserActivityLog, ProgramsRiskLog, LoopholesRiskLog, \
    BasicSafetyLog, AttackDetectionLog, AppsLog
from zmad.models import ZTPUser
from userdata.models import UserCreditScoreDetails
from strategy.models import CreditGlobalAction
from asset.models import Device
from ztp_backend.settings import BASE_DIR
from docxtpl import DocxTemplate

DOC_JSON_TEMPLATE = {
    "doctitle": "",
    "company": "",
    "name": "",
    "username": "",
    "group": "",
    "phone": "",
    "email": "",
    "safety_score": "",
    "safety_level": "",
    "singed_terminal": 0,
    "risk_terminal": 0,
    "apps_number": 0,
    "last_login_ip": "",
    "user_score": [
        {
            "date": "",
            "score": 0,
            "level": ""
        }],
    "user_activity": [
        {
            "date": "",
            "score": 0,
            "strategy": "",
            "platform": "",
            "url": "",
            "city": "",
            "ip": "-"},
        ],
    "device_list": [
        {
            "name": "",
            "device_uuid": "",
            "device_type_str": "",
            "version": "",
            "mac_addr": "",
            "IP": "",
            "safety": "",
            "program_risk_count": 2,
            "loopholes_risk_count": 0,
            "danger_app_count": 0,
            "basic_safety_count": 0,
            "attack_detection_count": 0,
            "program_risk": [
                {
                    "category": "",
                    "name": "",
                    "hash": "",
                    "path": "",
                    "date": ""
                }
            ],
            "loopholes_risk": [
                {
                    "code": "",
                    "name": "",
                    "release_time": "",
                    "date": "",
                    "level": "",
                    "desc": "",
                    "advice": "",
                    "patch": ""
                }],
            "basic_safety": [
                {
                    "name": "",
                    "result": "",
                    "date": "",
                    "advice": "",
                    "patch": ""
                }],
            "attack_detection": [
                {
                    "attack_type": "",
                    "date": "",
                    "attack_name": "",
                    "level": "",
                    "rule": "",
                    "rule_id": "",
                    "desc": "",
                    "device": ""
                }]
        },
    ]
}


def handler_user_info(user: ZTPUser):
    json_data = dict()
    level_map = {
        0: "安全用户", 1: "低风险用户", 2: "中风险用户", 3: "高风险用户", None: "-"
    }
    platform_map = {
        1: "app", 2: "windows", 3: "web", 4: "linux", None: "-"
    }
    loopholes_level_map = {
        1: '低危', 2: "中危", 3: "高危", 4: "严重", None: "-"
    }
    json_data['doctitle'] = ''
    json_data['company'] = ''
    json_data['user_score'] = list()
    json_data['user_activity'] = list()
    json_data['device_list'] = list()
    # 处理基础信息
    json_data['name'] = user.name
    json_data['username'] = user.username
    json_data['group'] = user.belong_to.name
    json_data['phone'] = user.phone
    json_data['email'] = user.email
    json_data['safety_score'] = user.safety_score
    json_data['safety_level'] = CreditGlobalAction.get_user_level(user.safety_score)
    json_data['last_login_ip'] = user.last_ip
    # 处理用户行为历史分
    month_range = datetime.datetime.now() - datetime.timedelta(days=30)
    user_score_list = UserCreditScoreDetails.objects.filter(datetime__gt=month_range, user=user).all()
    for user_score in user_score_list:
        temp_data = {
            "date": str(user_score.datetime.date()),
            "score": user_score.credit_score,
            "level": level_map[user_score.level]
        }
        json_data['user_score'].append(temp_data)
    # 处理用户行为日志
    user_activities = UserActivityLog.objects.filter(username=user.username).order_by('-log_time')[:30]
    for user_activity in user_activities:
        temp_data = {
            "date": user_activity.log_time,
            "activity": user_activity.activity,
            "strategy": user_activity.strategy,
            "platform": platform_map[user_activity.platform],
            "url": user_activity.url,
            "city": user_activity.city,
            "ip": user_activity.ip
        }
        json_data['user_activity'].append(temp_data)
    # 计算用户访问应用总数
    apps_number = len(UserActivityLog.objects.mongo_distinct(
                'url',
                {
                    'url': {
                        '$exists': True,
                        '$ne': ''
                    },
                    "username": user.username
                }
            ))
    json_data['apps_number'] = apps_number
    # 处理用户注册设备
    device_list = Device.objects.filter(user=user).all()
    signed_terminal = len(device_list)
    risk_terminal = Device.objects.filter(user=user, is_secure=False).count()
    for device in device_list:
        device_info = {
            "name": device.name,
            'device_uuid': device.device_uuid,
            "device_type_str": device.device_type_str,
            "version": device.version,
            "mac_addr": device.mac_addr,
            "IP": device.IP,
            "safety": "安全" if device.is_secure else "风险",
            "program_risk_count": 0,
            "loopholes_risk_count": 0,
            "danger_app_count": 0,
            "basic_safety_count": 0,
            "attack_detection_count": 0,
            'program_risk': [],
            "loopholes_risk": [],
            "danger_app": [],
            "basic_safety": [],
            "attack_detection": []
        }
        pr = ProgramsRiskLog.objects.filter(device_uuid=device.device_uuid).order_by("-log_time").first()
        if pr:
            date = pr.date
            attributes = ['trojans', 'infection', 'worm', 'hack', 'grey', 'risk', 'rubbish', 'others']
            for attribute in attributes:
                for i in getattr(pr, attribute):
                    temp_data = {
                        "category": i.category,
                        "name": i.name,
                        "hash": i.hash,
                        "path": i.path,
                        "date": date
                    }
                    device_info['program_risk'].append(temp_data)
        lr = LoopholesRiskLog.objects.filter(device_uuid=device.device_uuid).order_by("-log_time").first()
        if lr:
            date = lr.date
            attributes = ['serious', 'high', 'medium', 'low']
            for attribute in attributes:
                for i in getattr(lr, attribute):
                    temp_data = {
                        "code": i.code,
                        "name": i.name,
                        "release_time": i.release_time,
                        "level": loopholes_level_map[i.level],
                        "date": date,
                        "desc": i.desc,
                        "advice": i.advice,
                        "patch": i.patch
                    }
                    device_info['loopholes_risk'].append(temp_data)
        bs = BasicSafetyLog.objects.filter(device_uuid=device.device_uuid).order_by("-log_time").first()
        if bs:
            date = bs.date
            for d in bs.detection:
                temp_data = {
                    "name": d.name,
                    "result": d.result,
                    "date": date,
                    "advice": d.advice,
                    "patch": d.patch
                }
                device_info['basic_safety'].append(temp_data)
        ad = AttackDetectionLog.objects.filter(device_uuid=device.device_uuid).order_by("-log_time").first()
        if ad:
            date = ad.date
            for a in ad.attack:
                temp_data = {
                    "attack_type": a.attack_type,
                    "date": date,
                    "attack_name": a.attack_name,
                    "level": loopholes_level_map[a.level],
                    "rule": a.rule,
                    "rule_id": a.rule_id,
                    "desc": a.desc,
                    "device": a.advice
                }
                device_info['attack_detection'].append(temp_data)
        apps = AppsLog.objects.filter(device_uuid=device.device_uuid).order_by("-log_time").first()
        if apps:
            date = apps.date
            type_map = {'apps_danger': "危险应用", 'apps_harmless': '有害应用', 'apps_risk': '风险应用'}
            attributes = ['apps_danger', 'apps_harmless', 'apps_risk']
            for attribute in attributes:
                _type = type_map[attribute]
                for i in getattr(apps, attribute):
                    temp_data = {
                        "danger_type": _type,
                        "program_name": i.program_type,
                        "md5": i.md5,
                        "package_name": i.package_name,
                        "apk_path": i.apk_path,
                        "virus_name": i.virus_name,
                        "virus_description": i.virus_description,
                        "date": date
                    }
                    device_info['danger_app'].append(temp_data)
        device_info['danger_app_count'] = len(device_info['danger_app'])
        device_info['program_risk_count'] = len(device_info['program_risk'])
        device_info['loopholes_risk_count'] = len(device_info['loopholes_risk'])
        device_info['basic_safety_count'] = len(device_info['basic_safety'])
        device_info['attack_detection_count'] = len(device_info['attack_detection'])

        json_data['device_list'].append(device_info)
    json_data['signed_terminal'] = signed_terminal
    json_data['risk_terminal'] = risk_terminal
    return json_data


def exportWord(json_data, outFilePath='.'):
    try:
        context = json_data
        # report_template = "/Users/zugzwang/projects/ztp-api/tools/doc/sdp_userbehavior_report_template.docx"
        report_template = os.path.join(BASE_DIR, "tools/doc/sdp_userbehavior_report_template.docx")
        logging.info(report_template)
        doc = DocxTemplate(report_template)
        # 生成主docx
        doc.render(context)
        doc.save(outFilePath)
        logging.info("成功导出文档")
        return True
    except Exception as e:
        logging.error(traceback.format_exc(e))
        return False


if __name__ == '__main__':
    exportWord('', '/Users/zhuangzejian/projects/ztp-api/tools/doc/test.docx')